package com.zhia.demo.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zhia.demo.constont.RootPath;
import com.zhia.demo.dao.NovelDao;
import com.zhia.demo.entity.NovelEntity;
import com.zhia.demo.exception.FileTypeException;
import com.zhia.demo.service.NovelService;
import com.zhia.demo.vo.*;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.ResourceUtils;
import org.springframework.web.multipart.MultipartFile;
import org.thymeleaf.util.StringUtils;

import java.io.*;
import java.nio.file.Files;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

/**
 * @author DONG
 * @create 2023/10/24 18:07
 */
@Service
public class NovelServiceImpl extends ServiceImpl<NovelDao, NovelEntity> implements NovelService {

    private List<ContentVo> contents = new ArrayList<>();

    @Override
    public PageResultVo PageInfo(String cont, Integer page) {
        Page<NovelEntity> pageResult = page(new Page<>(page, 4),
                new QueryWrapper<NovelEntity>()
                        .like("title", cont)
                        .or().like("author", cont)
                        .orderByDesc("hot")
        );
        PageResultVo pageResultVo = new PageResultVo();
        pageResultVo.setBooks(pageResult.getRecords());
        pageResultVo.setTotal(pageResult.getTotal());
        pageResultVo.setMaxPage(pageResult.getPages());
        return pageResultVo;
    }

    @Override
    public ContentVo getBookContent(Integer chapter) {
        if (chapter >= 0 && chapter <= contents.size())
            return contents.get(chapter);
        else
            return null;
    }

    @Override
    public List<NovelEntity> getBooksByUserId(Integer id) {
        return baseMapper.selectList(new QueryWrapper<NovelEntity>().eq("uploader", id).orderByAsc("create_time"));
    }

    @Override
    public ResultVo saveBook(AddRequestVo requestVo, int userId) {
        ResultVo resultVo = new ResultVo();
        String imgSrc;
        String txtSrc;
        NovelEntity novelEntity = new NovelEntity();
        novelEntity.setId(UUID.randomUUID().toString().replace("-", ""));
        novelEntity.setTitle(requestVo.getName());
        novelEntity.setAuthor(requestVo.getAuthor());
        novelEntity.setIntro(requestVo.getIntroduction());
        novelEntity.setHot(0L);
        novelEntity.setCreateTime(new Timestamp(new Date().getTime()));
        novelEntity.setUploader(userId);

        try {
            imgSrc = "cover/" + fileUp(requestVo.getImage(), 1);
            novelEntity.setCover(imgSrc);
        } catch (IOException e) {
            resultVo.setCode(1L);
            resultVo.setMessage("图片上传失败");
            return resultVo;
        } catch (FileTypeException e) {
            resultVo.setCode(1L);
            resultVo.setMessage("图片上传失败: 文件类型不匹配");
            return resultVo;
        }

        try {
            txtSrc = "txt/" + fileUp(requestVo.getSrc(), 2);
            novelEntity.setContent(txtSrc);
        } catch (IOException e) {
            resultVo.setCode(1L);
            resultVo.setMessage("小说上传失败");
            return resultVo;
        } catch (FileTypeException e) {
            resultVo.setCode(1L);
            resultVo.setMessage("小说上传失败: 文件类型不匹配");
            return resultVo;
        }


        baseMapper.insert(novelEntity);
        return resultVo;
    }

    @Override
    public void hotAddById(String id) {
        baseMapper.hotAddById(id);
    }

    @Override
    public ResultVo updateBook(String id, AddRequestVo requestVo) {
        ResultVo resultVo = new ResultVo();
        NovelEntity oldNovel = baseMapper.selectById(id);
        NovelEntity novelEntity = new NovelEntity();
        novelEntity.setId(id);
        novelEntity.setTitle(requestVo.getName());
        novelEntity.setAuthor(requestVo.getAuthor());
        novelEntity.setIntro(requestVo.getIntroduction());
        novelEntity.setHot(0L);
        String imgSrc;
        String txtSrc;
        if (!StringUtils.isEmpty(requestVo.getImage().getOriginalFilename())) {
            try {
                imgSrc = "cover/" + fileUp(requestVo.getImage(), 1);
                novelEntity.setCover(imgSrc);

            } catch (Exception e) {
                resultVo.setCode(1L);
                resultVo.setMessage("上传失败");
                resultVo.setData(oldNovel);
                return resultVo;
            }
            deleteFile(oldNovel.getCover());
        }

        if (!StringUtils.isEmpty(requestVo.getSrc().getOriginalFilename())) {
            try {
                txtSrc = "txt/" + fileUp(requestVo.getSrc(), 2);
                novelEntity.setContent(txtSrc);

            } catch (Exception e) {
                resultVo.setCode(1L);
                resultVo.setMessage("上传失败");
                resultVo.setData(oldNovel);
                return resultVo;
            }
            deleteFile(oldNovel.getContent());
        }
        baseMapper.updateById(novelEntity);
        resultVo.setData(baseMapper.selectById(id));
        return resultVo;
    }

    @Override
    public BookVo getBookById(String id) {
        //根据id查询小说
        NovelEntity book = baseMapper.selectById(id);
        if (book != null) {
            //创建一个BookVo对象
            BookVo bookVo = new BookVo();
            //将查询到的实体类数据复制到BookVo对象中
            BeanUtils.copyProperties(book, bookVo);
            try {
                //调用readTxt方法读取txt文件
                readTxt(book.getContent());
                //将读取的章节数赋值给BookVo对象
                bookVo.setChapters(contents.size());
            } catch (IOException e) {
                //如果读取失败，将章节数赋值为0
                bookVo.setChapters(0);
            }

            return bookVo;
        } else {
            return null;
        }
    }

    /**
     * 上传文件（图书上传到静态目录挂载文件夹txt文件夹，封面上传到静态目录挂载文件夹的cover文件夹）
     *
     * @param document: 需要上传的文件
     * @param type:     要上传的文件类型 1: 图片文件, 2: 文本文件
     */
    private String fileUp(MultipartFile document, Integer type) throws IOException {
        //获取文件根路径
        File rootPath = ResourceUtils.getFile(RootPath.ROOT_PATH);
        //获取文件名
        String documentName = document.getOriginalFilename();
        //判断文件名是否为空
        if (StringUtils.isEmpty(documentName)) {
            return "";
        } else {
            //获取文件后缀
            String hzName = documentName.substring(documentName.lastIndexOf("."));
            //生成文件名
            documentName = UUID.randomUUID() + hzName;
            String path;
            //判断文件类型
            if (type == 2 && hzName.equals(".txt")) {
                path = rootPath.getPath() + File.separator + "txt";
            } else if (type == 1 && hzName.equals(".jpg") || hzName.equals(".png") || hzName.equals(".jpeg")) {
                path = rootPath.getPath() + File.separator + "cover";
            } else {
                throw new FileTypeException("文件类型不支持");
            }
            //创建文件夹
            File file = new File(path);
            if (!file.exists()) {
                if (!file.mkdirs())
                    throw new IOException();
            }
            //拼接文件路径
            String finalPath = path + File.separator + documentName;
            System.out.println(finalPath);
            //实现上传功能
            document.transferTo(new File(finalPath));
            return documentName;
        }
    }

    /**
     * 获取选中小说的所有章节内容
     *
     * @param src: 小说在服务器的路径
     */
    private void readTxt(String src) throws IOException {
        //获取文件路径
        File file = ResourceUtils.getFile(RootPath.ROOT_PATH + src);
        String s;
        String p = "^第[0-9一两二三四五六七八九十百千]+[集回章].+";
        InputStreamReader in = null;
        List<ContentVo> bookContentList = new ArrayList<>();
        try {
            in = new InputStreamReader(Files.newInputStream(file.toPath()));
            BufferedReader br = new BufferedReader(in);
            int i = 0;
            String key = br.readLine();
            List<String> lines = new ArrayList<>();
            bookContentList.add(new ContentVo(key, lines, true));
            while ((s = br.readLine()) != null) {
                if (s.trim().matches(p)) {
                    key = s;
                    lines = new ArrayList<>();
                    i++;
                    bookContentList.add(new ContentVo(key, lines, true));
                } else {
                    if (!"".equals(s.trim())) {
                        bookContentList.get(i).getLines().add(s);
                    }
                }
            }
            bookContentList.get(bookContentList.size() - 1).setHasNextChapter(false);
        } finally {
            try {
                if (in != null)
                    in.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        contents = bookContentList;
    }

    private boolean deleteFile(String src) {
        if (StringUtils.isEmpty(src)) {
            return false;
        } else {
            File file = null;
            try {
                file = ResourceUtils.getFile(RootPath.ROOT_PATH + src);
            } catch (FileNotFoundException e) {
                return false;
            }
            if (file.exists()) {
                return file.delete();
            } else {
                return false;
            }
        }

    }
}
